package Classes.GameUtils// ActionScript file
{
	import flash.geom.Point;

	/**
	 *直线相关方程 
	 * @author jamesge
	 * 
	 */	
	public class GU_StraightEquation
	{	
		public static const COINCIDENT:String="coincident";/*重合*/
		public static const INTERSECTANT:String="intersectant";/*相交*/
		public static const PARALLELED:String="paralleled";/*平行*/
		public static const VERTICAL:String="vertical";/*垂直*/
		
		/**
		 *通过两点获得直线方程 
		 * ax+by+c=0;
		 * @param p1
		 * @param p2
		 * @return 直线方程参数数组
		 * 
		 * 
		 */		
		public static function getStraightEquationByTwoPoint(p1:Point,p2:Point):Array
		{
			var par1:Number;
			var par2:Number;
			var par3:Number;
			if(p1.x==p2.x)
			{
				par1=1;
				par2=0;
				par3=-p1.x;
			}
			else if(p1.y==p2.y)
			{
				par1=0;
				par2=1;
				par3=-p1.y;
			}
			else
			{
				par1=(p2.y-p1.y)/(p1.x-p2.x);
				par2=1;
				par3=-(par1*p1.x+p1.y);
			}
			return [par1,par2,par3];
		}
		
		/**
		 *通过顶点和角度获得直线方程 
		 * @param p1
		 * @param angle
		 * @return 
		 * 
		 */		
		public static function getStraightEquationByPointAndAngle(p1:Point,angle:Number):Array
		{
			var par1:Number;
			var par2:Number;
			var par3:Number;
			if(angle==Math.PI/2 || angle==Math.PI*3/2)
			{
				par1=1;
				par2=0;
				par3=-p1.x;
			}
			else
			{
				var k:Number=Math.tan(angle);
				par1=-k;
				par2=1;
				par3=k*p1.x-p1.y;
			}
			return [par1,par2,par3];
		}
		
		/**
		 *获得直线与圆的交点 
		 * @param straightAry [a1,b1,c1]
		 * @param roundAry [a2:圆形坐标点X,b2:圆形坐标点Y,c2:圆半径]
		 * @return length=0,无交点;length=1,1个交点;length=2,2个交点;
		 * 
		 */		
		public static function getCrossPointsOfStraightAndRound(straightAry:Array,roundAry:Array):Array
		{
			var returnAry:Array=new Array;
			var a2:Number=straightAry[0];
			var b2:Number=straightAry[1];
			var c2:Number=straightAry[2];
			var a1:Number=roundAry[0];
			var b1:Number=roundAry[1];
			var c1:Number=roundAry[2];
			var x:Number;
			var y:Number;
			var p1_x:Number;
			var p1_y:Number;
			var p2_x:Number;
			var p2_y:Number;
			var a:Number;
			var b:Number;
			var c:Number;
			var delta:Number;
			if(b2==0)
			{
				x=-c2/a2;
				a=1;
				b=-2*b1;
				c=b1*b1-c1*c1+a1*a1+(c2*c2)/(a2*a2)+(2*a1*c2)/a2;
				delta=b*b-4*a*c;
				if(delta>0)
				{
					p1_y=(-b+Math.sqrt(delta))/(2*a);
					p2_y=(-b-Math.sqrt(delta))/(2*a);
					returnAry.push(new Point(x,p1_y));
					returnAry.push(new Point(x,p2_y));
				}
				else if(delta==0)
				{
					y=-b/(2*a);
					returnAry.push(new Point(x,y));
				}
			}
			else
			{
				a=1+a2*a2;
				b=2*a2*c2+2*b1*a2-2*a1;
				c=a1*a1+c2*c2+2*b1*c2+b1*b1-c1*c1;
				delta=b*b-4*a*c;
				if(delta>0)
				{
					p1_x=(-b+Math.sqrt(delta))/(2*a);
					p2_x=(-b-Math.sqrt(delta))/(2*a);
					p1_y=-(c2+a2*p1_x);
					p2_y=-(c2+a2*p2_x);
					returnAry.push(new Point(p1_x,p1_y));
					returnAry.push(new Point(p2_x,p2_y));
				}
				else if(delta==0)
				{
					x=-b/(2*a);
					y=-(c2+a2*x);
					returnAry.push(new Point(x,y));
				}
			}
			return returnAry;
		}
		
		/**
		 *获得两条直线的关系 
		 * @param s1
		 * @param s2
		 * @return 
		 * 
		 */		
		public static function getRelationOfTwoStraight(s1:Array,s2:Array):String
		{
			var par:Number;
			if(s1[0] == s2[0] && s1[1] == s2[1] && s1[2] == s2[2])
			{
				return COINCIDENT;
			}
			else if(s1[0]*s2[1]==s1[1]*s2[0])
			{
				return PARALLELED;
			}
			else if(s1[0]*s2[0]==-s1[1]*s2[1])
			{
				return VERTICAL;
			}
			else
			{
				return INTERSECTANT;
			}
		}
		
		/**
		 *判定某坐标点是否位于直线上 
		 * @param point
		 * @return 
		 * 
		 */		
		public static function checkOnLine(point:Point,straight:Array):Boolean
		{
			if(point.x*straight[0]+point.y*straight[1]+straight==0)
			{
				return true;
			}
			return false;
		}
		
		/**
		 *获得两条直线的交点（两点平行或重合时焦点为NULL） 
		 * @param s1
		 * @param s2
		 * @return 
		 * 
		 */		
		public static function getCrossingPointOfTwoStraight(s1:Array,s2:Array):Point
		{
			var relation:String=getRelationOfTwoStraight(s1,s2);
			if(relation==COINCIDENT || relation==PARALLELED)
			{
				return null;
			}
			var px:Number=(s2[2]*s1[1]-s1[2]*s2[1])/(s1[0]*s2[1]-s2[0]*s1[1]);
			var py:Number;
			if(s1[1]==0)
			{
				py=-(s2[0]*px+s2[2])/s2[1];
			}
			else
			{
			    py=-(s1[0]*px+s1[2])/s1[1];
			}
			return new Point(px,py);
		}
		
		/**
		 *计算两点之间的距离 
		 * @param p1
		 * @param p2
		 * @return 
		 * 
		 */		
		public static function getDistanceOfTwoPoint(p1:Point,p2:Point):Number
		{
			return Math.sqrt(Math.pow(p2.x-p1.x,2)+Math.pow(p2.y-p1.y,2));
		}
		
		/**
		 *从任意的点数组中获取多边形顶点数组 
		 * @param pointsAry
		 * @return 
		 * 
		 */		
		public static function getPolygonVertexsAryFromPointsAry(pointsAry:Array):Array
		{
			if(pointsAry.length<3)throw new Error("顶点太少，无法构成多边形");
			var firstPoint:Point=pointsAry[0];
			var nowIndex:int=0;
			var i:int;
			for(i=1;i<pointsAry.length;i++)
			{
				var checkPoint:Point=pointsAry[i];
				if(checkPoint.y<firstPoint.y)
				{
					firstPoint=checkPoint;
					nowIndex=i;
				}
			}
			pointsAry.splice(nowIndex,1);
			var returnAry:Array=new Array;
			var nowCheckPoint:Point=firstPoint;
			returnAry.push(nowCheckPoint);
			while(pointsAry.length)
			{
				var prePoint:Point;
				if(returnAry.length>1)prePoint=returnAry[returnAry.length-2] as Point;
				var preValue:Number=prePoint?getAtan2Value(nowCheckPoint,prePoint):Math.PI/2;
				var minValuePoint:Point;
				var minValuePointIndex:int;
				var minValue:Number=Math.PI*2;
				for(i=0;i<pointsAry.length;i++)
				{
					var checkValuePoint:Point=pointsAry[i];
					var checkValue:Number=preValue-getAtan2Value(nowCheckPoint,checkValuePoint);
					if(checkValue<0)checkValue+=Math.PI*2;
					if(checkValue<minValue)
					{
						minValuePoint=checkValuePoint;
						minValuePointIndex=i;
						minValue=checkValue;
					}
				}
				if(returnAry.length>2)
				{
					var toFirstValue:Number=preValue-getAtan2Value(nowCheckPoint,firstPoint);
					if(toFirstValue<0)toFirstValue+=Math.PI*2;
					if(toFirstValue<=minValue)
					{
						break;
					}
				}
				returnAry.push(minValuePoint);
				pointsAry.splice(minValuePointIndex,1);
				nowCheckPoint=minValuePoint;
			}
			function getAtan2Value(nowPoint:Point,targetPoint:Point):Number
			{
				var returnNum:Number=Math.atan2(targetPoint.x-nowPoint.x,targetPoint.y-nowPoint.y);
				//trace("atan2="+returnNum);
				return returnNum;
			}
			if(returnAry.length<3)throw new Error("顶点太少或成直线，无法构成多边形");
			return returnAry;
		}
	}
}
